---
title: 'Variants'
---

# Variants

To add groups of styles based on theme values, you can take advantage of the
_Variants_ feature. Variants allow you to define the styles used across multiple
buttons, typographic elements, or any element in your `theme` object.

For example, you can define `primary` and `secondary` variants for buttons and
use colors from the theme.

```js
// example theme with variants
{
  colors: {
    primary: '#07c',
    secondary: '#639',
  },
  buttons: {
    primary: {
      color: 'white',
      bg: 'primary',
    },
    secondary: {
      color: 'white',
      bg: 'secondary',
    },
  },
}
```

With the `theme` object above, the `buttons` variants can be referenced by any
tag through [the `sx` prop](/sx-prop). Inside `sx`, the variant should begin
with a top-level key from the theme, then use dot notation to access nested
objects.

```jsx
<button sx={{ variant: 'buttons.primary' }} />
```

When using the [built-in components](/components), you can use the `variant`
prop directly on components, instead of inside the `sx` object.

Most [components have their own variant group](/components/variants) (“variant
group” being a top-level theme key, e.g. the
[`Button` component](/components/button) uses `buttons`), and some also have a
default variant they’ll utilize from that variant group (e.g. `Button` defaults
to using `primary`).

This means using `<Button />` without specifying a variant has the same result
as the snippet above, since the default variant name (`primary`) matches a
variant name inside the `buttons` group. If you want a different variant from
the same group, you can give its key without specifying the group:

```jsx
<Button variant="secondary" />
```

You can also use variants outside of a component’s default variant group with
dot notation. This is especially useful for combining layout components without
further nesting your DOM, such as adding container styles to a grid or flexbox.
By using the [`Grid` component](/components/grid) here with a variant, you’re
able to use `Grid`’s props combined with the variant styles.

```jsx
<Grid variant="layouts.container" columns={3} gap={3} />
```

<Note>

Variants can use any name you choose, and deeply nested objects can be accessed
with dot notation. You could use this to organize more complex variants, like
`<Button variant="outline.small" />`, which would access the
`buttons.outline.small` object from the theme.

</Note>

## Color Modes

Variants will also work with [color modes](/color-modes). With the example
below, the primary button will adapt its colors based on the current color mode.

```js
// example theme with button variants and color modes
{
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#0c7',
    modes: {
      dark: {
        text: '#000',
        background: '#fff',
        primary: '#0c7',
      },
    },
  },
  buttons: {
    primary: {
      color: 'background', // use the page background color for an inverted effect
      bg: 'primary',
    },
  }
}
```

## Typography

Variants can also be used to create typographic styles, similar to how graphics
applications store text styles. This allows you to define core typographic
values and use them as complete styles, but still override individual values
when needed.

```js
// example theme with typographic variants
{
  fonts: {
    body: 'system-ui, sans-serif',
    heading: 'Poppins, sans-serif',
    monospace: 'Menlo, monospace',
  },
  lineHeights: {
    body: 1.5,
    heading: 1.125,
  },
  fontWeights: {
    body: 400,
    heading: 900,
    bold: 700,
  },
  letterSpacings: {
    heading: '-0.05em',
    caps: '0.1em',
  },
  text: {
    heading: {
      fontFamily: 'heading',
      fontWeight: 'heading',
      lineHeight: 'heading',
      letterSpacing: 'heading',
    },
    display: {
      fontFamily: 'heading',
      fontWeight: 'heading',
      lineHeight: 'heading',
      letterSpacing: 'heading',
      fontSize: [ 5, 6, 7 ],
    },
    caps: {
      textTransform: 'uppercase',
      letterSpacing: 'caps',
    },
  },
}
```

These variants can then be used in the `theme.styles` object, with the `sx`
prop, or with the [`Text`](/components/text) or [`Heading`](/components/heading)
components.

```jsx
// example usage of typographic variants
<h1 sx={{ variant: 'text.display' }} />
<p sx={{ variant: 'text.caps' }} />
<h2
  sx={{
    variant: 'text.heading',
    // overriding the default styles
    fontWeight: 'body',
  }}
/>
```

## `styles` variants

Variants inside the `styles` object, while usable through the same mechanisms as
regular variants, are also used for other Theme UI APIs.

- The entire [`styles` object](/theme-spec#styles) can style child HTML elements
  or Markdown content, via the [`BaseStyles` component](/api/#basestyles)
- If the [`useRootStyles` configuration option](/theming#configuration-flags) is
  enabled, the `styles.root` object will style the `<html>` element
- [`Themed` components](/mdx/themed) will use their respective variant from
  inside `styles`, e.g. `<Themed.h2>` uses `styles.h2`

## Themeable layout components

Variants can also be used to create themeable layout components. This is
especially useful when creating [Gatsby themes][], where you'd like certain
parts of your page layout to be customizable.

Using the `variant` key in the `sx` prop allows you to define styles for a
component that can optionally be overridden from the `theme` object. When the
variant is undefined in the `theme`, no additional styles are applied to the
element.

Read the [Layouts Guide](/guides/layouts) to learn more.

[styled system css]: https://styled-system.com/css
[gatsby themes]: https://www.gatsbyjs.org/docs/themes/
